/**********
    @name: editor组件
    @describtion: props: title:字段别名 ,value: 字段值
    @author:liubingye
    @date:2023-02-10 18:36:37
***********/
<template>
  <div class="tinymce-box">
    <div class="editor-header">
      <h2>{{modelTitle}}</h2>
    </div>
    <el-form-item :rules="editorRule" :prop="editorName"></el-form-item>
    <Editor
        :id="editorName"
        v-model="content"
        :init="init"
        tag-name="div"
    />
    <ImageUpload v-model:showDialog="showAxupImgs" :limit="20" @getImage="insertImage" :isToJpg="true"></ImageUpload>
  </div>
</template>

<script>

//引入tinymce编辑器
import Editor from '@tinymce/tinymce-vue'

//引入node_modules里的tinymce相关文件文件
import tinymce from 'tinymce/tinymce' //tinymce默认hidden，不引入则不显示编辑器
import 'tinymce/themes/silver'  //编辑器主题，不引入则报错
import 'tinymce/icons/default'  //引入编辑器图标icon，不引入则不显示对应图标
import 'tinymce/plugins/advlist'; //高级列表
import 'tinymce/plugins/anchor'; //锚点
import 'tinymce/plugins/autolink'; //自动链接
import 'tinymce/plugins/autoresize'; //编辑器高度自适应,注：plugins里引入此插件时，Init里设置的height将失效
import 'tinymce/plugins/autosave'; //自动存稿
import 'tinymce/plugins/charmap'; //特殊字符
import 'tinymce/plugins/code'; //编辑源码
import 'tinymce/plugins/codesample'; //代码示例
import 'tinymce/plugins/directionality'; //文字方向
import 'tinymce/plugins/emoticons'; //表情
import 'tinymce/plugins/fullpage'; //文档属性
import 'tinymce/plugins/fullscreen'; //全屏
import 'tinymce/plugins/help'; //帮助
import 'tinymce/plugins/hr'; //水平分割线
import 'tinymce/plugins/image'; //插入编辑图片
import 'tinymce/plugins/importcss'; //引入css
import 'tinymce/plugins/insertdatetime'; //插入日期时间
import 'tinymce/plugins/link'; //超链接
import 'tinymce/plugins/lists'; //列表插件
import 'tinymce/plugins/media'; //插入编辑媒体
import 'tinymce/plugins/nonbreaking'; //插入不间断空格
import 'tinymce/plugins/pagebreak'; //插入分页符
import 'tinymce/plugins/paste'; //粘贴插件
import 'tinymce/plugins/preview'; //预览
import 'tinymce/plugins/print'; //打印
import 'tinymce/plugins/quickbars'; //快速工具栏
import 'tinymce/plugins/save'; //保存
import 'tinymce/plugins/searchreplace'; //查找替换
import 'tinymce/plugins/tabfocus'; //切入切出，按tab键切出编辑器，切入页面其他输入框中
import 'tinymce/plugins/table'; //表格
import 'tinymce/plugins/template'; //内容模板
import 'tinymce/plugins/textcolor'; //文字颜色
import 'tinymce/plugins/textpattern'; //快速排版
import 'tinymce/plugins/toc'; //目录生成器
import 'tinymce/plugins/visualblocks'; //显示元素范围
import 'tinymce/plugins/visualchars'; //显示不可见字符
import 'tinymce/plugins/wordcount'; //字数统计
import '@npkg/tinymce-plugins/importword' //三方插件导入word
import '@npkg/tinymce-plugins/indent2em'

import { watch, ref, onMounted, computed } from "vue";
import {useStore} from "vuex";
import {convertHexToBase64, parseRtf} from "@/utils/tools";
import { singleUpload } from "@/utils/upload";

export default {
  name: 'TEditor',
  components: {
    Editor
  },
  props: {
    title: {
      type: String,
      default: ''
    },
    modelValue: {
      type: String,
      default: ''
    },
    editorId: {
      type: String,
      default: 'myedit'
    },
    isDestroy: {
      type: Boolean,
      default: false
    },
    field: {
      type: String,
      default: ''
    },
    required: {
      type: Boolean,
      default: false
    },
  },
  emits: { 'update:modelValue': null },
  setup(props,context) {
    const store = useStore()
    const init = {
      language_url: process.env.BASE_URL + 'tinymce/langs/zh_CN.js',  //引入语言包文件
      language: 'zh_CN',  //语言类型

      skin_url: process.env.BASE_URL+'tinymce/skins/ui/oxide',  //皮肤：浅色

      plugins: 'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave ',  //插件配置
      toolbar: ['importword axupimgs media link table | code undo redo | formatselect fontselect fontsizeselect','lineheight bullist numlist | forecolor backcolor bold italic underline strikethrough | alignleft aligncenter alignright alignjustify outdent indent indent2em | blockquote subscript superscript'],  //工具栏配置，设为false则隐藏
      menubar: false, //菜单栏配置，设为false则隐藏，不配置则默认显示全部菜单，也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
      fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px',  //字体大小
      font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;',  //字体样式
      lineheight_formats: "12px 14px 16px 20px 24px 26px 30px 32px 34px 36px",  //行高配置，也可配置成"12px 14px 16px 20px"这种形式

      height: 400,  //注：引入autoresize插件时，此属性失效
      placeholder: '在这里输入文字',
      branding: false,  //tiny技术支持信息是否显示
      resize: false,  //编辑器宽高是否可变，false-否,true-高可变，'both'-宽高均可，注意引号
      elementpath: false,  //元素路径是否显示

      content_css: process.env.BASE_URL+'tinymce/tinycontent.css',
      content_style: "img {max-width:100%;}",  //直接自定义可编辑区域的css样式
      paste_data_images: true,  //图片是否可粘贴
      convert_urls: false,
      // eslint-disable-next-line no-unused-vars
      images_upload_handler: (blobInfo, success, failure, progress) => {
        // 方法1：用base64的图片形式上传图片
        // const img = 'data:image/jpeg;base64,' + blobInfo.base64()
        // success(img)

        // 方法2：上传oos
        let data = new FormData()
        data.append('file', blobInfo.blob())
        // 获取图片文件的宽高属性
        data.append('startX', 0)
        data.append('startY', 0)
        data.append('path', 'content')
        data.append('type', 0)
        const imageUrl = URL.createObjectURL(blobInfo.blob())
        const img = new Image()
        img.src = imageUrl
        img.onload = function() {
          const width = img.width
          const height = img.height
          URL.revokeObjectURL(imageUrl)
          data.append('cropWidth', width)
          data.append('cropHeight', height)
          data.append('scaledWidth', width)
          data.append('scaledHeight', height)
        }
        singleUpload(data, store.state.content.singleActionUrl).then(res => {
          if(res.code === 20000){
            success(res.data.url)
          }
        })
      },
      init_instance_callback: function (editor) {
        editor.execCommand("selectAll")
        editor.selection.getRng().collapse(false)
        editor.focus()

        editor.on("paste", (evt) => {
          const clipboardData = evt.clipboardData;
          const isImage =
              clipboardData.types.length &&
              clipboardData.types.join("").includes("Files");
          if (!isImage) {
            //------------------------粘贴word核心代码开始-------------------------
            const hexStrings = parseRtf(
                evt.clipboardData.getData("text/rtf")
            );
            // 获取base64图片数据
            const base64Images = hexStrings.map((hexObj) => {
              return convertHexToBase64(hexObj.hex);
            });
            setTimeout(() => {
              const wordImages =
                  tinymce.activeEditor.dom.doc.querySelectorAll(
                      'img[src*="file://"]'
                  );
              wordImages.forEach((item, index) => {
                item.src = `data:${hexStrings[index].type};base64,${base64Images[index]}`;
                tinymce.activeEditor.uploadImages();
              });
            }, 200);
            //------------------------粘贴word核心代码结束-------------------------
            return;
          }
          const file = clipboardData.files[0];
          if (!file || !file.name || !(file.name.toLowerCase().indexOf(".png") !== -1 || file.name.toLowerCase().indexOf(".gif") !== -1 || file.name.toLowerCase().indexOf(".jpeg") !== -1 || file.name.toLowerCase().indexOf(".jpg") !== -1))
          {
            this.$message.error("您粘贴的不是图片请检查！");
            return;
          }
          if (file.size / 1024 / 1024 > 5) {
            this.$message.error(
                "上传失败，图片大小请控制在 5M 以内"
            );
            return;
          }
        });
      },

      // eslint-disable-next-line no-unused-vars
      urlconverter_callback: (url, node, onSave, name) => {
        if(node === 'img' && url.startsWith('blob:')){
          tinymce.activeEditor && tinymce.activeEditor.uploadImages();
        }
        return url;
      },
      paste_postprocess: function (plugin,args) {
        if(process.env.NODE_ENV === 'development') console.log(args)
        args.content = 'helloworld'
      },

      setup: (editor) => {
        editor.ui.registry.addButton('axupimgs',{
          text: `<i class="iconfont">&#xe609;</i>`,
          tooltip: '批量上传',
          onAction: () => {
            showAxupImgs.value = true
          }
        })
      }
    }
    tinymce.init
    const editorRule = ref([])
    const validateEdit = (rule, value, callback) => {
      if(value === ''){
        callback(new Error(props.title + '不能为空'))
      } else {
        callback()
      }
    }
    const editorName = ref(props.editorId)
    const content = computed({
      get: () => props.modelValue,
      set: val => {
        context.emit('update:modelValue', val);
      }
    })
    const modelTitle = ref(props.title)
    watch(() => props.isDestroy,() => {
      tinymce.editors[editorName.value].destroy()
    })
    const showAxupImgs = ref(false)
    const insertImage = (imgList) => {
      let imgContent = ``
      imgList.forEach(item => {
        let _img = `<p><img src="${item.url}" /></p>`
        imgContent = imgContent + _img
      })
      tinymce.editors[editorName.value].insertContent(imgContent+'<p></p>')
    }
    onMounted(() => {
      if(props.required){
        editorRule.value.push({validator: validateEdit,trigger: 'change'})
      }
    })
    return {
      content,
      modelTitle,
      init,
      editorName,

      showAxupImgs,
      insertImage,
      editorRule
    }
  }
}
</script>

<style lang="scss" scoped>
  .tinymce-box{
    width: 100%;
    .editor-header{
      height: 60px;
      line-height: 60px;
      h2{
        font-size: 18px;
        color: #333333;
      }
    }
    ::v-deep(.el-form-item){
      margin: 0;
    }
    ::v-deep(.el-form-item__content){
      margin-left: 0!important;
      .el-form-item__error{
        top:-14px;
      }
    }
  }
  ::v-deep(.axupimg-box .el-dialog__body){
    padding: 0;
  }
  .axupimg-box{
    .inner-axupimg-box{
      display: flex;
      height: 450px;
      .axupimg-upload-box{
        width: 520px;
        height: 100%;
        .local-upload{
          padding: 10px;
          width: 500px;
          .local-upload-list{
            height: 330px;
            display: flex;
            flex-wrap: wrap;
            position: relative;
            align-content: flex-start;
            &>div{
              height: 110px;
              width: 110px;
              margin-right: 10px;
              margin-bottom: 10px;
              background-color: #F0F2F7;
            }
            li{
              height: 110px;
              width: 110px;
              box-sizing: border-box;
              list-style: none;
              border: 1px solid #dcdfe6;
              display: flex;
              align-items: center;
              justify-content: center;
              position: relative;
              border-radius: 5px;
              cursor: pointer;
              .img-box{
                height: 108px;
                width: 108px;
                display: flex;
                justify-content: center;
                align-items: center;
                img{
                  max-width: 108px;
                  max-height: 108px;
                }
              }
              .progress-box{
                width: 100px;
                position: absolute;
                bottom: 5px;
              }
              .remove-upload{
                color: $placeholderColor;
                position: absolute;
                right: 5px;
                top: 8px;
                cursor: pointer;
                display: none;
              }
              .choose-check{
                position: absolute;
                left: 5px;top: 0;
              }
              &:hover{
                .remove-upload{
                  display: block;
                }
              }
              &.is-choose{
                border-color: $mainColor;
              }
            }
          }
        }
        .online-upload{
          padding: 10px;
          width: 500px;
          .online-upload-list{
            display: flex;
            flex-wrap: wrap;
            height: 375px;
            .online-upload-item{
              height: 115px;width: 115px;
              border-radius: 6px;
              background-color: $borderColor;
              display: flex;
              align-items: center;
              justify-content: center;
              margin-right: 10px;
              margin-bottom: 10px;
              cursor: pointer;
              box-sizing: border-box;
              img{
                max-width: 100%;
                max-height: 100%;
              }
              &:nth-child(4n){
                margin-right: 0;
              }
              &.is-choose{
                border: 1px solid $mainColor;
              }
            }
          }
        }
      }
      .axupimg-list-box{
        width: 180px;
        height: 100%;
        border-left: 1px solid #dcdfe6;
        box-sizing: border-box;
        padding: 10px;
        p{
          margin-bottom: 10px;
        }
        .chose-img-list{
          height: 400px;
          justify-content: center;
          flex-direction: column;
          .chose-img-box{
            height: 130px;width: 145px;
            display: flex;
            align-items: center;
            justify-content: center;
            background-color: #F0F2F7;
            margin-bottom: 10px;
            border-radius: 6px;
            img{
              max-height: 100%;
              max-width: 100%;
            }
          }
        }
      }
    }
  }
</style>
